package aufgabe2;

import java.util.*;

public class MatrixArrayListe implements MatrixInterface<MatrixArrayListe> {

	ArrayList<Pair>[] NULLMATRIX = new ArrayList[3];
	private int rows;
	private int columns;

	private List<Pair>[] matrix;

	MatrixArrayListe(List<Pair>[] matrix, int rows, int columns) {
		this.rows = rows;
		this.columns = columns;
		this.matrix = matrix;
		for (int i = 0; i < 3; i++) {
			NULLMATRIX[i] = new ArrayList<Pair>();
		}
	}

	public double get(int i, int j) {
		double erg = 0;
		
		System.out.println("Get Methode: "+matrix[i]);
		System.out.println("i "+i+"j "+j);

		for (int x = 0; x < matrix[i].size(); x++) {

			if (matrix[i].get(x).getPos() == j)
				erg = matrix[i].get(x).getVal();

		}
		return erg;
	}

	public void set(int i, int j, double x) {
		boolean b = false;

		for (Pair p : matrix[i]) {
			if (p.getPos() == j) {
				p.setVal(x);
				b = true;
			}
		}

		if (!b)
			matrix[i].add(new Pair(j, x));

	}

	@Override
	public void add(MatrixArrayListe m) {
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				if (get(i, j) == 0.0 && m.get(i, j) == 0.0) {
				} else if (get(i, j) == 0.0 && m.get(i, j) != 0.0) {
					matrix[i].add(new Pair(j, m.get(i, j)));

				} else {
					set(i, j, get(i, j) + m.get(i, j));
				}
			}
		}
	}

	@Override
	public void skaMul(double f) {
		for (int i = 0; i < rows; i++) {
			for (Pair p : matrix[i]) {
				p.setVal(p.getVal() * f);
			}
		}
	}

	@Override
	public void mul(MatrixArrayListe m) {
		MatrixArrayListe temp = new MatrixArrayListe(NULLMATRIX, rows, columns);
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				for (int k = 0; k < columns; k++) {
					temp.set(i, j, temp.get(i, j) + get(i, k) * m.get(k, j));
				}
			}
		}
		matrix = temp.getMatrixStructure();
	}

	@Override
	public void pow(int i) {
		MatrixArrayListe erg = new MatrixArrayListe(matrix, rows, columns);
		for (int j = 0; j < i - 1; j++) {
			erg.mul(this);
		}
		matrix = erg.getMatrixStructure();
	}

	@Override
	public void pot(int i) {
		MatrixArrayListe erg = new MatrixArrayListe(matrix, rows, columns);

		if (i == 1) {
			matrix = erg.getMatrixStructure();
		}

		else if (i == 2) {
			erg.mul(this);

		}

		else if (i % 2 == 1) {
			erg.pot(i - 1);
			erg.mul(this);

		} else {
			erg.pot(i / 2);
			erg.mul(this);
		}

		matrix = erg.getMatrixStructure();

	}

	public List<Pair>[] getMatrixStructure() {
		return matrix;
	}

	public int getRows() {
		return rows;
	}

	public void setRows(int rows) {
		this.rows = rows;
	}

	public int getColumns() {
		return columns;
	}

	public void setColumns(int columns) {
		this.columns = columns;
	}

	public int toLenght() {
		int count = 0;
		for (int i = 0; i < matrix.length; i++) {
			for (Pair p : matrix[i]) {
				count++;
			}

		}
		return count * 2;
	}

	public String toString() {
		StringBuilder str = new StringBuilder();
		for (int i = 0; i < matrix.length; i++) {
			for (Pair p : matrix[i]) {
				str.append(p.getVal() + " ");
			}
			str.append("\n");
		}
		return str.toString();
	}

	/**
	 * Innere Klasse zum darstellen der Paare innerhalb der Listen
	 * 
	 */
	public static class Pair {

		int j;
		double a;

		/**
		 * Konstruktor
		 * 
		 * @param j
		 * @param a
		 */
		public Pair(int j, double a) {
			this.j = j;
			this.a = a;
		}

		/**
		 * Gibt den Wert an der entsprechenden Position zur�ck
		 * 
		 * @param j
		 * @return Der Wert des Matrix-Feldes
		 */
		public double getVal() {
			return a;
		}

		/**
		 * Setzt den Wert an der entsprechenden Position
		 * 
		 * @param a
		 */
		public void setVal(double a) {
			this.a = a;
		}

		public int getPos() {
			return j;
		}

		public String toString() {
			return "" + a;
		}

	}

}
